/**
 * Copyright (C) 2011 GreenSoft S.A.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ar.com.greensoft.neosystem.services;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;

import ar.com.greensoft.neosystem.dao.DaoException;
import ar.com.greensoft.neosystem.dao.LocalidadDao;
import ar.com.greensoft.neosystem.dao.NoSuchEntityException;
import ar.com.greensoft.neosystem.dao.PaisDao;
import ar.com.greensoft.neosystem.dao.ProvinciaDao;
import ar.com.greensoft.neosystem.model.Authority;
import ar.com.greensoft.neosystem.model.User;
import ar.com.greensoft.neosystem.model.address.Localidad;
import ar.com.greensoft.neosystem.model.address.Pais;
import ar.com.greensoft.neosystem.model.address.Provincia;
import ar.com.greensoft.neosystem.model.references.ISO3166_1;
import ar.com.greensoft.neosystem.model.references.ISO3166_2AR;
import ar.com.greensoft.neosystem.util.ApplicationRoles;

/**
 * Initialization of CRM Module
 * 
 *  
 * @author Jorge E. Villaverde
 * @since 09/06/2011
 * @version 1.0.0
 */
@Singleton 
@Startup
public class CrmInit {
	private static final String LOCALIDADES_CHACO = "localidades_chaco.txt";

	private static final String USER_ADMIN = "admin";

	private static final String CHECK_DEFAULT_VALUES_KEY = "ar.com.greensoft.neosystem.CHECK_DEFAULT_VALUES";

	@Inject
	private Logger logger;
	
	@EJB
	private ProvinciaDao provinciaDao;
	@EJB
	private PaisDao paisDao;
	@EJB
	private LocalidadDao localidadDao;
	@EJB
	private UserService userService;

    @PostConstruct 
    public void initializeCrm() {
    	
    	try {
			boolean checkDefaultValues = Boolean.parseBoolean(System.getProperty(CHECK_DEFAULT_VALUES_KEY, "false"));
			
			if(checkDefaultValues){
		    	chechDefaultUser();
				checkPaises();  	
				checkProvincias();
				checkLocalidades();
			}
		} catch (Exception e) {
			logger.severe(e.getMessage());
		}    	
    }

	private void checkLocalidades() {
		Provincia chaco = provinciaDao.findByName(ISO3166_2AR.AR_H_NOMBRE.toString());
		
		try {
			List<String> localidades = readLocalidadesFromResource();
			
			if(localidades == null)
				return;
			
			for(String localidad : localidades){
				Localidad l = localidadDao.findByName(localidad);
				
				if(l != null)
					logger.info("Localidad: " + localidad + "\tFOUND");
				else{
					logger.info("Provincia: " + localidad + "\tNOT FOUND");
					l = new Localidad();
					l.setProvincia(chaco);
					l.setName(localidad);
					localidadDao.persist(l);
					logger.info("Localidad: " + localidad + "\tCREATED");
				}				
			}
			
		} catch (IOException e) {
			logger.severe(e.getMessage());
		} catch (DaoException e) {
			logger.severe(e.getMessage());
		}
		
	}

	private List<String> readLocalidadesFromResource() throws IOException {
		InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(LOCALIDADES_CHACO);
		if(is != null)
			return readLines(is);
		return null;
	}
	
	public List<String> readLines(InputStream is) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
        List<String> lines = new ArrayList<String>();
        String line = null;
        while ((line = bufferedReader.readLine()) != null) {
            lines.add(line);
        }
        bufferedReader.close();
        return lines;
    }

	private void chechDefaultUser() {
		try {
			User admin = userService.findUserByUsername(USER_ADMIN);
			if(admin == null){
				logger.info("Creating Defaul admin User.");
				admin = userService.createUser(USER_ADMIN, USER_ADMIN);
									
				Authority userAuthority = new Authority();
				userAuthority.setUser(admin);
				userAuthority.setAuthority(ApplicationRoles.ROLE_USER);

				Authority adminAuthority = new Authority();
				adminAuthority.setUser(admin);
				adminAuthority.setAuthority(ApplicationRoles.ROLE_ADMIN);
				
				userService.grantAuthority(userAuthority);
				userService.grantAuthority(adminAuthority);
				
				logger.info("Default User: " + admin.getUsername() + "\tCREATED");
			}			
		} catch (ServiceException e) {
			logger.severe(e.getMessage());
		}		
	}

	private void checkProvincias() {
		Pais argentina = paisDao.findByCode(ISO3166_1.AR);
		if(argentina == null){
			logger.warning("No se ha encontrado el Pais: Argentina");
			return;
		}
		
		for(ISO3166_2AR codigoISO: ISO3166_2AR.values()) {
			try {
				Provincia provincia = provinciaDao.findByName(codigoISO.toString());
				if(provincia != null)
					logger.info("Provincia: " + codigoISO.toString() + "\tFOUND");
				else{
					logger.info("Provincia: " + codigoISO.toString() + "\tNOT FOUND");
					provincia = new Provincia();
					provincia.setName(codigoISO.toString());
					provincia.setPais(argentina);
					provinciaDao.persist(provincia);
					logger.info("Provincia: " + codigoISO.toString() + "\tCREATED");
				}
			} catch (NoSuchEntityException e) {
				logger.severe("Error: " + e.getMessage());
			} catch (Exception e) {
				logger.severe("Error: " + e.getMessage());
			}
		}
	}

	private void checkPaises() {
		for(ISO3166_1 codigoISO: ISO3166_1.values()) {
			try {
				Pais pais = paisDao.findByCode(codigoISO);
				if(pais != null)
					logger.info("Pais: " + codigoISO.toString() + "\tFOUND");
				else{
					logger.info("Pais: " + codigoISO.toString() + "\tNOT FOUND");
					pais = new Pais();
					pais.setCodigoISO(codigoISO);
					pais.setName(codigoISO.getLabel());
					paisDao.persist(pais);
					logger.info("Pais: " + codigoISO.toString() + "\tCREATED");
				}
			} catch (NoSuchEntityException e) {
				logger.severe("Error: " + e.getMessage());
			} catch (Exception e) {
				logger.severe("Error: " + e.getMessage());
			}
			
		}		
	}

    @PreDestroy 
    public void destroyCrm() { 
    }
    
}
